﻿using Common;
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace CarPCBATest.Procedure
{
    public enum TurnLampStatus
    {
        AllOff,
        OnlyLeftOn,
        OnlyRightOn,
        AllOn
    }

    internal class PcbCANControl
    {
        /// <summary>
        /// 刹车灯状态 1-on 0-off
        /// </summary>
        public static bool BreakLampStatus { get; set; }

        /// <summary>
        /// 转向灯状态
        /// </summary>
        public static TurnLampStatus TurnLampStatus { get; set; }

        /// <summary>
        /// 位置灯状态
        /// </summary>
        public static bool PosLampStatus { get; set; }

        private static int cmd20ACount = 0;
        private static int cmd21ACount = 0;
        private static bool init = false;

        private static void Init()
        {
            cmd20ACount = 0;
            cmd21ACount = 0;
            init = true;
        }

        [Conditional("DEVICE")]
        public static void Connect()
        {
            if (init)
            {
                return;
            }
            try
            {
                CanControl.Connect();
                CanControl.Init(0, 500);
                CanControl.StartCan(0);
                Init();
                StartSendCmd();
            }
            catch (Exception)
            {
                init = false;
                throw;
            }
        }

        public static void DisConnect()
        {
            if (!init)
            {
                return;
            }
            init = false;
            Thread.Sleep(500);

            CanControl.Close();
        }

        static int CallCount = 0;

        private static void StartSendCmd()
        {
            Mylog.Info("调用StartSendCmd次数" + CallCount++.ToString());
            Thread thread = new Thread(() =>
            {
                try
                {
                    while (init)
                    {
                        SendCmd21A();   //20ms
                        Thread.Sleep(5);
                        //Mylog.Debug("0StartSendCmd:" + sw.ElapsedMilliseconds);
                        SendCmd52A();   //50ms
                        Thread.Sleep(10);
                        //Mylog.Debug("1StartSendCmd:" + sw.ElapsedMilliseconds);
                        SendCmd20A();   //50ms

                        Thread.Sleep(5);
                        SendCmd21A();
                        //Mylog.Debug("2StartSendCmd:" + sw.ElapsedMilliseconds);
                        Thread.Sleep(20);
                        //Mylog.Debug("3StartSendCmd:" + sw.ElapsedMilliseconds);
                        SendCmd21A();
                        Thread.Sleep(15);
                        //Mylog.Debug("0StartSendCmd:" + sw.ElapsedMilliseconds);
                        SendCmd52A();   //50ms
                        Thread.Sleep(5);
                        SendCmd21A();
                        Thread.Sleep(5);
                        //Mylog.Debug("1StartSendCmd:" + sw.ElapsedMilliseconds);
                        SendCmd20A();   //50ms
                        Thread.Sleep(15);
                        SendCmd21A();   //20ms
                        Thread.Sleep(20);
                    }
                }
                catch (Exception ex)
                {
                    Mylog.Error(ex, ex.Message);
                }
            });
            thread.Priority = ThreadPriority.Highest;
            thread.Start();
            //Task.Run(() =>
            //{
            //while (init)
            //{
            //    SendCmd21A();   //20ms
            //    Thread.Sleep(18);
            //    SendCmd52A();   //50ms
            //    Thread.Sleep(18);
            //    SendCmd21A();
            //    Thread.Sleep(10);
            //    SendCmd20A();   //50ms
            //    Thread.Sleep(15);
            //}
            //while (init)
            //{
            //    SendCmd21A();   //20ms
            //    Thread.Sleep(5);
            //    SendCmd52A();   //50ms
            //    Thread.Sleep(5);
            //    SendCmd21A();
            //    Thread.Sleep(8);
            //    SendCmd20A();   //50ms
            //    Thread.Sleep(10);
            //}

            //while (init)
            //{
            //    SendCmd21A();   //20ms
            //    Thread.Sleep(17);
            //}
            //});
            //Task.Run(() =>
            //{
            //    while (init)
            //    {
            //        SendCmd52A();   //50ms
            //        Thread.Sleep(47);
            //    }
            //});
            //Task.Run(() =>
            //{
            //    while (init)
            //    {
            //        SendCmd20A();   //50ms
            //        Thread.Sleep(47);
            //    }
            //});
            Task.Run(() =>
            {
                try
                {
                    while (init)
                    {
                        CanControl.ReadDataFromUsb(0);
                        Thread.Sleep(1000);
                    }
                }
                catch (Exception ex)
                {
                    Mylog.Error(ex, ex.Message);
                }
            });
        }

        private static void SendCmdExt(uint id, string data)
        {
            //Stopwatch sw = new Stopwatch();
            //sw.Start();
            //lock (locer)
            {
                CanControl.SendCmd(0, id, data);
            }
            //Mylog.Debug("CAN发送耗时0：" + sw.ElapsedMilliseconds.ToString());
            //Mylog.Info($"id[{id.ToString("X4")} data[{data}]]");
        }

        private static void SendCmd20A()
        {
            Stopwatch sw20A = Stopwatch.StartNew();

            if (cmd20ACount == 15)
            {
                cmd20ACount = 0;
            }
            byte b0 = 0x00;
            byte b1 = 0x00;
            byte b2 = 0x20;
            byte b3 = 0x00;
            byte b4 = 0x00;
            byte b5 = 0x0A;
            byte b6 = 0x88;
            byte b7 = 0x28;
            b2 |= (byte)cmd20ACount;
            if (BreakLampStatus)    //制动灯
            {
                b2 |= 0x10;
            }
            else
            {
                b2 |= 0x00;
            }
            if (PosLampStatus)  //位置灯
            {
                b7 |= 0x10;
            }
            else
            {
                b7 |= 0x00;
            }
            b3 = (byte)Rcm.CRC_Cal(1091, (byte)cmd20ACount, (byte)(BreakLampStatus ? 1 : 0));
            string cmd20A = $"{b0.ToString("X2")} {b1.ToString("X2")} {b2.ToString("X2")} {b3.ToString("X2")} {b4.ToString("X2")} {b5.ToString("X2")} {b6.ToString("X2")} {b7.ToString("X2")}";

            //Mylog.Debug("0SendCmd21A耗时：" + sw20A.ElapsedMilliseconds);
            SendCmdExt(0x20A, cmd20A);  //50ms
                                        //ThreadPool.QueueUserWorkItem(_ => SendCmdExt(0x20A, cmd20A));
            cmd20ACount++;
            //Mylog.Debug("耗时：" + sw20A.ElapsedMilliseconds);
        }

        private static void SendCmd21A()
        {
            Stopwatch sw21A = Stopwatch.StartNew();
            if (cmd21ACount == 15)
            {
                cmd21ACount = 0;
            }
            byte b0 = 0x00;
            byte b1 = 0x00;
            byte b2 = 0x00;
            byte b3 = 0x00;
            byte b4 = 0xC0;
            byte b5 = 0x00;
            byte b6 = 0x00;
            byte b7 = 0x00;
            byte turnLightValue = 0;
            switch (TurnLampStatus)
            {
                case TurnLampStatus.AllOff:
                    turnLightValue = 0;
                    break;

                case TurnLampStatus.OnlyLeftOn:
                    turnLightValue = 1;
                    break;

                case TurnLampStatus.OnlyRightOn:
                    turnLightValue = 2;
                    break;

                case TurnLampStatus.AllOn:
                    turnLightValue = 3;
                    break;

                default:
                    turnLightValue = 3;
                    break;
            }
            b4 |= (byte)cmd21ACount;
            b4 |= (byte)(turnLightValue << 4);
            b5 = (byte)Rcm.CRC_Cal(158, (byte)cmd21ACount, turnLightValue);

            string cmd21A = $"{b0.ToString("X2")} {b1.ToString("X2")} {b2.ToString("X2")} {b3.ToString("X2")} {b4.ToString("X2")} {b5.ToString("X2")} {b6.ToString("X2")} {b7.ToString("X2")}";
            //Mylog.Debug("0SendCmd21A耗时：" + sw21A.ElapsedMilliseconds);
            SendCmdExt(0x21A, cmd21A);  //20ms
            //ThreadPool.QueueUserWorkItem(_ => SendCmdExt(0x21A, cmd21A));
            //Mylog.Debug("耗时：" + sw21A.ElapsedMilliseconds);

            cmd21ACount++;
        }

        private static readonly object locer = new object();

        private static void SendCmd52A()
        {
            //Stopwatch sw52A = Stopwatch.StartNew();
            SendCmdExt(0x52A, "2A 50 FF FF FF FF FF FF");   //50ms
            //Mylog.Debug("耗时：" + sw52A.ElapsedMilliseconds);
            //ThreadPool.QueueUserWorkItem(_ => SendCmdExt(0x52A, "2A 50 FF FF FF FF FF FF"));
        }
    }
}